#pragma once
#include "Vector3.h"
#include "Vector4.h"

template <class T>
class Matrix44
{
public:
	static const size_t MATRIX44_SIZE = sizeof(T) * 16;

    // constructor/destructor
    inline Matrix44() { identity(); }
	inline Matrix44(const T* arr);
    inline ~Matrix44() {}
    
    // copy operations
    Matrix44<T>& operator=(const Matrix44<T>& other);

    // accessors
    T &operator()(unsigned int i, unsigned int j);
    T operator()(unsigned int i, unsigned int j) const;

    // comparison
    //bool operator==( const Matrix44& other ) const;
    //bool operator!=( const Matrix44& other ) const;
    //bool IsIdentity() const;

    //void Clean();
    inline void identity();

    //Matrix44<T> affineInverse() const;
    Matrix44<T> inverse() const;
    Matrix44<T> transpose() const;

    // transformations
    Matrix44<T>& translation(const Vector3<T>& xlate);
    Matrix44<T>& rotation(const Vector3<T>& i,const Vector3<T>& j,const Vector3<T>& k);
    Matrix44<T>& rotation(const Vector3<T>& axis, T radius);

    // operators
	Vector4<T> Matrix44<T>::operator*( const Vector4<T>& vector ) const;

    // multiplication
    Matrix44<T>& operator*=( const Matrix44<T>& matrix );
    Matrix44<T> operator*( const Matrix44<T>& matrix ) const;

    // low-level data accessors - implementation-dependent
    operator T*() { return m; }
    operator const T*() const { return m; }

    // member variables
    T m[16];
};

#include "Matrix44.inl"

typedef Matrix44<float> mat4f;